package com.erp.erp_ui.business.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.erp.enums.ModuleTypeEnum;
import com.erp.enums.OperationStatusEnum;
import com.erp.enums.OperationTypeEnum;
import com.erp.enums.ProductTypeEnum;
import com.erp.erp_entitys.business.entity.*;
import com.erp.erp_entitys.business.req.*;
import com.erp.erp_entitys.business.rsp.AlternativeSupplierRsp;
import com.erp.erp_entitys.business.rsp.CompanyLogo;
import com.erp.erp_entitys.business.rsp.OfferProductStatisticsRsp;
import com.erp.erp_entitys.log.entity.DataInfoLogEntity;
import com.erp.erp_entitys.money.entity.ReceivePaymentEntity;
import com.erp.erp_entitys.warehouse.entity.AnnexEntity;
import com.erp.erp_entitys.warehouse.entity.TempAnnexEntity;
import com.erp.erp_entitys.warehouse.req.DictionaryInfoReq;
import com.erp.erp_entitys.warehouse.rsp.DictionaryInfoRsp;
import com.erp.erp_entitys.warehouse.rsp.ProductAnnexInfoRsp;
import com.erp.erp_entitys.warehouse.rsp.ProductPartsInfoRsp;
import com.erp.erp_servers.business.*;
import com.erp.erp_servers.log.IDataInfoLogService;
import com.erp.erp_servers.warehouse.IAnnexService;
import com.erp.erp_servers.warehouse.IStockService;
import com.erp.erp_servers.warehouse.ITempAnnexService;
import com.erp.erp_ui.business.req.*;
import com.erp.erp_ui.business.vo.*;
import com.erp.erp_ui.money.req.OperationReq;
import com.erp.erp_ui.warehouse.enums.DataIsValidEnum;
import com.erp.erp_ui.warehouse.req.AnnexReq;
import com.erp.erp_ui.warehouse.vo.AnnexVo;
import com.erp.utils.*;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName : OfferService
 * @Description : 出口业务-报价业务逻辑层
 * @Author : lst
 * @Date: 2021-01-14 11:00
 */
@Service
public class OfferService {

    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(CarryDetailService.class);

    /**
     * 报价接口
     */
    private final IOfferService offerService;

    /**
     * 报价明细接口
     */
    private final IOfferDetailService offerDetailService;

    /**
     * 报价配件接口
     */
    private final IOfferProductPartsService offerProductPartsService;

    /**
     * 报价费用接口
     */
    private final IOfferCostService offerCostService;

    /**
     * 附件接口
     */
    private final IAnnexService annexService;

    /**
     * 临时附件接口
     */
    private final ITempAnnexService tempAnnexService;

    /**
     * 库存接口
     */
    private final IStockService stockService;

    /**
     * 外销接口
     */
    private final IExportContractProductService exportContractProductService;

    /**
     * 外销主表接口
     */
    private final IExportContractService exportContractService;

    /**
     * 操作日志信息接口
     */
    private final IDataInfoLogService dataInfoLogService;

    @Autowired
    public OfferService(IOfferService offerService,
                        IOfferDetailService offerDetailService,
                        IOfferProductPartsService offerProductPartsService,
                        IOfferCostService offerCostService,
                        IAnnexService annexService,
                        ITempAnnexService tempAnnexService,
                        IStockService stockService,
                        IExportContractProductService exportContractProductService,
                        IExportContractService exportContractService,
                        IDataInfoLogService dataInfoLogService) {
        this.offerService = offerService;
        this.offerDetailService = offerDetailService;
        this.offerProductPartsService = offerProductPartsService;
        this.offerCostService = offerCostService;
        this.annexService = annexService;
        this.tempAnnexService = tempAnnexService;
        this.stockService = stockService;
        this.exportContractProductService = exportContractProductService;
        this.exportContractService = exportContractService;
        this.dataInfoLogService = dataInfoLogService;
    }

    /**
     * 获取字典信息
     * @param dictionaryInfosReq 查询条件
     * @return 返回字典信息
     */
    public List<DictionaryInfoRsp> getDictionary(DictionaryInfoReq dictionaryInfosReq){
        return stockService.getDictionaryInfo(dictionaryInfosReq);
    }


    /**
     * 获取报价信息
     * @param req 查询参数
     * @return 报价信息
     */
    public PageInfo<OfferPageListVo> getListByPage(OfferPageListReq req){
        //初始化回参对象集合
        List<OfferPageListVo> voList = new ArrayList<>();
        if(StringUtils.isBlank(req.getOperationNo()) && StringUtils.isBlank(req.getSalesmanCode()) && StringUtils.isBlank(req.getDeptOperationCode()) && StringUtils.isBlank(req.getDeptSalesmanCode())){
            PageInfo pageInfo = new PageInfo();
            pageInfo.setList(voList);
            return pageInfo;
        }
        //初始化查询对象
        OfferListReq query = new OfferListReq();
        //赋值
        BeanUtils.copyProperties(req, query);
        if(StringUtils.isNotEmpty(req.getBillNo())){
            //去掉前后空格
            query.setBillNo(req.getBillNo().trim());
        }
        //设置排序字段,重新映射字段,避免sql注入
        //setQueryField(query);
        //调用接口查询结果
        List<OfferEntity> offerList = offerService.getOfferListInfo(query);
        PageInfo pageInfo = new PageInfo(offerList);
        if(CollectionUtils.isEmpty(offerList)){
            pageInfo.setList(voList);
            return pageInfo;
        }
        for(OfferEntity offer : offerList){
            OfferPageListVo vo = new OfferPageListVo();
            //赋值
            BeanUtils.copyProperties(offer, vo);
            //报价日期
            vo.setTime(DateUtils.format(offer.getTime(), DateUtils.DATE_PATTERN));
            //报价有效期限
            vo.setTermOfValidity(DateUtils.format(offer.getTermOfValidity(), DateUtils.DATE_PATTERN));
            //交货期限
            vo.setDeliveryPeriod(DateUtils.format(offer.getDeliveryPeriod(), DateUtils.DATE_PATTERN));
            //状态
            vo.setStatusStr(OperationStatusEnum.getDescById(offer.getStatus()));

            voList.add(vo);
        }

        pageInfo.setList(voList);
        return pageInfo;
    }

    /**
     * 获取报价信息
     * @param req 查询参数
     * @return 报价信息
     */
    public List<OfferPageListVo> getList(OfferPageListReq req){
        //初始化回参对象集合
        List<OfferPageListVo> voList = new ArrayList<>();
        //初始化查询对象
        OfferListReq query = new OfferListReq();
        //赋值
        BeanUtils.copyProperties(req, query);
        if(StringUtils.isNotEmpty(req.getBillNo())){
            //去掉前后空格
            query.setBillNo(req.getBillNo().trim());
        }
        //设置排序字段,重新映射字段,避免sql注入
        //setQueryField(query);
        //调用接口查询结果
        List<OfferEntity> offerList = offerService.getOfferListInfo(query);
        if(CollectionUtils.isEmpty(offerList)){
            return voList;
        }
        for(OfferEntity offer : offerList){
            OfferPageListVo vo = new OfferPageListVo();
            //赋值
            BeanUtils.copyProperties(offer, vo);
            //报价日期
            vo.setTime(DateUtils.format(offer.getTime(), DateUtils.DATE_PATTERN));
            //报价有效期限
            vo.setTermOfValidity(DateUtils.format(offer.getTermOfValidity(), DateUtils.DATE_PATTERN));
            //交货期限
            vo.setDeliveryPeriod(DateUtils.format(offer.getDeliveryPeriod(), DateUtils.DATE_PATTERN));
            //状态
            vo.setStatusStr(OperationStatusEnum.getDescById(offer.getStatus()));

            voList.add(vo);
        }

        return voList;
    }

    /**
     * 设置排序字段,重新映射字段,避免sql注入
     * @param query 排序字段
     */
    private void setQueryField(OfferListReq query){
        if(StringUtils.isEmpty(query.getField())){
            return;
        }
        switch (query.getField()){
            case "billNo":
                query.setField("bill_no");
                break;
            case "time":
                query.setField("time");
                break;
            case "customerName":
                query.setField("customer_name");
                break;
            case "countryName":
                query.setField("country_name");
                break;
            case "customerContactName":
                query.setField("customer_contact_name");
                break;
            case "contactEmail":
                query.setField("contact_email");
                break;
            case "termOfValidity":
                query.setField("term_of_validity");
                break;
            case "deliveryPeriod":
                query.setField("delivery_period");
                break;
            case "priceTermsName":
                query.setField("price_terms_name");
                break;
            case "totalQuotation":
                query.setField("total_quotation");
                break;
            case "salesman":
                query.setField("salesman");
                break;
            case "signingCompanyName":
                query.setField("signing_company_name");
                break;
        }
    }


    /**
     * 新增、修改
     * @param req 新增、修改入参
     * @param creator 创建人
     * @param createNo 创建人编码
     * @return 新增、修改结果
     */
    @Transactional(rollbackFor = Exception.class)
    public R add(AddOfferReq req, String creator, String createNo) throws ParseException {
        //一：单号唯一性校验
        boolean billNoCheckFlag = (null != req.getId() && req.getBillNo().equals(req.getNewBillNo()));
        if(!billNoCheckFlag){
            //单号做唯一校验
            boolean billNoFlag = checkRepeatBillNo(req.getBillNo());
            if(!billNoFlag){
                return R.buildError(ResultStatusEnum.BILL_NO_REPEAT);
            }
        }

        //二：报价主表新增
        Integer id = insert(req, creator, createNo);
        if(id == null){
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }

        //三：明细新增及对应配件
        insertDetail(req, id, creator, createNo);

        //四：费用新增
        addCost(req, id, creator, createNo);

        //五：添加附件信息
        boolean flag = addAnnex(req, id, creator, createNo);
        if(!flag){
            LOGGER.info("出口业务-报价-批量新增附件异常");
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }
        //删除临时附件信息
        deleteTempAnnex(req.getAnnexList());
        return R.build(ResultStatusEnum.SUCCESS);
    }

    /**
     * 费用新增
     * @param req 新增参数
     * @param id 报价id
     */
    private void addCost(AddOfferReq req, Integer id, String creator, String createNo){
        if(CollectionUtils.isEmpty(req.getCostList())){
            return;
        }
        List<OfferCostEntity> addCostList = new ArrayList<>();
        //费用id
        List<Integer> newIds = new ArrayList<>();
        for(AddOfferCostReq cost : req.getCostList()){
            OfferCostEntity updateReq = new OfferCostEntity();
            //赋值
            BeanUtils.copyProperties(cost, updateReq);

            if(null == cost.getId()){
                //新增

                //新增日志信息
                DataInfoLogEntity dataInfoLog = new DataInfoLogEntity();
                //模块主表id
                dataInfoLog.setParentId(id);
                //模块id
                dataInfoLog.setModuleId(ModuleTypeEnum.BUSINESS_OFFER.getId());
                //操作人编码
                dataInfoLog.setOperationCode(createNo);
                //操作人名称
                dataInfoLog.setOperationName(creator);
                //操作时间
                dataInfoLog.setOperationTime(new Date());
                //操作类型
                dataInfoLog.setOperationType(OperationTypeEnum.INSERT_DATA.getId());
                //操作内容
                dataInfoLog.setOperationContent("费用信息:");

                dataInfoLogService.insert(dataInfoLog);

                //父id
                updateReq.setParentId(id);
                //创建时间
                updateReq.setCreateDate(new Date());
                //设为有效
                updateReq.setValid(DataIsValidEnum.VALID.getId());

                addCostList.add(updateReq);
            }else {
                //修改

                OfferCostEntity offerCost = offerCostService.queryById(cost.getId());

                BeanChangeLogUtil logUtil = new BeanChangeLogUtil();
                String info = logUtil.contrastObj(offerCost, updateReq);
                if(StringUtils.isNotEmpty(info)){
                    //新增日志信息
                    DataInfoLogEntity dataInfoLog = new DataInfoLogEntity();
                    //模块主表id
                    dataInfoLog.setParentId(id);
                    //模块id
                    dataInfoLog.setModuleId(ModuleTypeEnum.BUSINESS_OFFER.getId());
                    //操作人编码
                    dataInfoLog.setOperationCode(createNo);
                    //操作人名称
                    dataInfoLog.setOperationName(creator);
                    //操作时间
                    dataInfoLog.setOperationTime(new Date());
                    //操作类型
                    //操作内容
                    dataInfoLog.setOperationContent("费用信息:" + info);
                    //操作类型
                    dataInfoLog.setOperationType(OperationTypeEnum.UPDATE_DATA.getId());

                    dataInfoLogService.insert(dataInfoLog);
                }
                //修改时间
                updateReq.setModifyTime(new Date());
                offerCostService.update(updateReq);
                newIds.add(updateReq.getId());
            }
        }
        //处理被删除的费用
        handleBeenDeletedCost(id, newIds);

        if(!CollectionUtils.isEmpty(addCostList)){
            //费用批量新增
            offerCostService.addList(addCostList);
        }
    }

    /**
     * 处理被删除的费用
     * @param id 报价id
     * @param newIds 费用id
     */
    private void handleBeenDeletedCost(int id, List<Integer> newIds){
        //修改-找出被删除的费用

        OfferCostEntity costReq = new OfferCostEntity();
        //设置报价id
        costReq.setParentId(id);
        //查询有效数据
        costReq.setValid(DataIsValidEnum.VALID.getId());
        //调用接口查询结果
        List<OfferCostEntity> costList = offerCostService.queryAll(costReq);
        if(!CollectionUtils.isEmpty(costList)){
            //获取id集合
            List<Integer> oldIds = costList.stream().map(p -> p.getId()).collect(Collectors.toList());
            //找出被删除的id
            Collection collection = new ArrayList(oldIds);
            collection.removeAll(newIds);
            if(collection.size() > 0){
                //遍历被删除的费用
                Iterator<Integer> ids = collection.iterator();
                while (ids.hasNext()){
                    int costId = ids.next();
                    OfferCostEntity updateReq = new OfferCostEntity();
                    //修改主键
                    updateReq.setId(costId);
                    //修改时间
                    updateReq.setModifyTime(new Date());
                    //设为无效
                    updateReq.setValid(DataIsValidEnum.INVALID.getId());

                    offerCostService.update(updateReq);
                }
            }
        }
    }

    /**
     * 批量处理临时附件信息，将临时附件设置为失效
     * @param annexReqs
     */
    private void deleteTempAnnex(List<AnnexReq> annexReqs){
        //没有附件
        if(CollectionUtils.isEmpty(annexReqs)){
            return;
        }
        //存在附件
        for(AnnexReq annex : annexReqs){
            if(null != annex.getNews()){
                //旧附件,不用修改
                continue;
            }
            TempAnnexEntity tempAnnex = new TempAnnexEntity();
            //设置临时附件id
            tempAnnex.setId(annex.getId());
            //设置修改时间
            tempAnnex.setUpdateTime(new Date());
            //将附件设置为失效
            tempAnnex.setValid(DataIsValidEnum.INVALID.getId());
            tempAnnexService.update(tempAnnex);
        }

    }

    /**
     * 附件新增
     * @param req 入参信息
     * @param id 付款id
     * @param operator 操作人
     * @param operatorNo 操作人编码
     * @return 是否新增成功(true:成功 false:失败 )
     */
    private boolean addAnnex(AddOfferReq req, Integer id, String operator, String operatorNo) {
        try {
            List<AnnexReq> annexReqs = req.getAnnexList();
            //没有附件,将该id关联的所有附件设为无效
            if(CollectionUtils.isEmpty(annexReqs)){
                AnnexEntity annexReq = new AnnexEntity();
                annexReq.setParentId(id);
                annexReq.setModuleId(ModuleTypeEnum.BUSINESS_OFFER.getId());
                List<AnnexEntity> annexList = annexService.queryAll(annexReq);
                if(!CollectionUtils.isEmpty(annexList)){
                    for(AnnexEntity annex : annexList){
                        AnnexEntity updateAnnex= new AnnexEntity();
                        updateAnnex.setId(annex.getId());
                        //将被删除的附件设为失效
                        updateAnnex.setValid(DataIsValidEnum.INVALID.getId());
                        annexService.update(updateAnnex);
                    }
                }
                return true;
            }
            //存在附件,新增附件信息
            List<AnnexEntity> list = new ArrayList<>();
            for(AnnexReq annexReq : annexReqs){
                if(null != annexReq.getNews()){
                    //属于旧附件,不新增
                    continue;
                }
                AnnexEntity annex = new AnnexEntity();
                BeanUtils.copyProperties(annexReq, annex);
                //设置关联模块id
                annex.setModuleId(ModuleTypeEnum.BUSINESS_OFFER.getId());
                //设置关联模块父id
                annex.setParentId(id);
                //设置上传时间
                annex.setUploadTime(DateUtils.convertStringToDate(annexReq.getUploadTime(), DateUtils.DATE_PATTERN));
                //设置修改时间
                annex.setUpdateTime(new Date());
                //设置操作人
                annex.setOperator(operator);
                //设置操作人编码
                annex.setOperatorNo(operatorNo);
                //设置数据有效
                annex.setValid(1);

                list.add(annex);
            }
            if(!CollectionUtils.isEmpty(list)){
                //附件批量新增
                annexService.batchInsert(list);
            }
            //获取删除的附件
            List<Integer> deleteAnnexIds = req.getDeleteAnnexIds();
            if(deleteAnnexIds.size() > 0){
                //存在被删除的旧附件，数据库删除
                for(Integer deleteAnnexId : deleteAnnexIds){
                    AnnexEntity annexEntity = new AnnexEntity();
                    //附件主键ID
                    annexEntity.setId(deleteAnnexId);
                    //将被删除的附件设为失效
                    annexEntity.setValid(DataIsValidEnum.INVALID.getId());
                    //删除时间
                    annexEntity.setUpdateTime(new Date());

                    annexService.update(annexEntity);
                }
            }
            return true;
        }catch (Exception e){
            throw new RuntimeException();
        }
    }

    /**
     * 明细新增
     * @param req 新增对象
     * @param id 报价id
     */
    public void insertDetail(AddOfferReq req, int id, String creator, String createNo) {
        if(!CollectionUtils.isEmpty(req.getDetailList())){
            //获取明细id集合
            List<Integer> newIds = new ArrayList<>();
            for(AddOfferDetailReq detailReq : req.getDetailList()){
                //初始化明细对象
                OfferDetailEntity offerDetail = new OfferDetailEntity();
                //赋值
                BeanUtils.copyProperties(detailReq, offerDetail);
                //设置付款id
                offerDetail.setParentId(id);
                //设置数据有效性(0:无效 1:有效)
                offerDetail.setValid(DataIsValidEnum.VALID.getId());
                if(null == detailReq.getId()){
                    if (req.getId() != null) {
                        //表明修改新增产品
                        //新增日志信息
                        DataInfoLogEntity dataInfoLog = new DataInfoLogEntity();
                        //模块主表id
                        dataInfoLog.setParentId(id);
                        //模块id
                        dataInfoLog.setModuleId(ModuleTypeEnum.BUSINESS_OFFER.getId());
                        //操作人编码
                        dataInfoLog.setOperationCode(createNo);
                        //操作人名称
                        dataInfoLog.setOperationName(creator);
                        //操作类型
                        dataInfoLog.setOperationType(OperationTypeEnum.INSERT_DATA.getId());
                        //操作时间
                        dataInfoLog.setOperationTime(new Date());
                        //操作内容
                        dataInfoLog.setOperationContent("产品信息:" + "产品编码:" + offerDetail.getProductCode() + ",规格编码:" + offerDetail.getSpecificationCode());

                        dataInfoLogService.insert(dataInfoLog);
                    }
                    //创建时间
                    offerDetail.setCreateDate(new Date());
                    //新增
                    offerDetailService.insert(offerDetail);
                    //获取明细id
                    Integer detailId = offerDetail.getId();
                    newIds.add(detailId);
                    //配件新增
                    if(!CollectionUtils.isEmpty(detailReq.getPartsList())){
                        //初始化配件对象集合
                        List<OfferProductPartsEntity> partsList = new ArrayList<>();
                        for(AddOfferProductPartsReq parts : detailReq.getPartsList()){
                            //初始化配件对象
                            OfferProductPartsEntity partsEntity = new OfferProductPartsEntity();
                            //赋值
                            BeanUtils.copyProperties(parts, partsEntity);
                            //报价id
                            partsEntity.setParentId(id);
                            //产品明细id
                            partsEntity.setProductDetailId(detailId);
                            //创建时间
                            partsEntity.setCreateDate(new Date());
                            //产品类型(1:成品 2:配件 默认为配件)
                            partsEntity.setProductType(ProductTypeEnum.FITTING.getId());
                            //设置数据有效性(0:无效 1:有效)
                            partsEntity.setValid(DataIsValidEnum.VALID.getId());

                            partsList.add(partsEntity);
                        }
                        if(!CollectionUtils.isEmpty(partsList)){
                            //新增配件
                            offerProductPartsService.addList(partsList);
                        }

                    }
                }else {
                    //修改

                    //添加修改日志
                    //获取修改前对象数据
                    OfferDetailEntity oldOffer = offerDetailService.queryById(offerDetail.getId());
                    BeanChangeLogUtil logUtil = new BeanChangeLogUtil();
                    String info = logUtil.contrastObj(oldOffer, offerDetail);
                    if(StringUtils.isNotEmpty(info)){
                        //新增日志信息
                        DataInfoLogEntity dataInfoLog = new DataInfoLogEntity();
                        //模块主表id
                        dataInfoLog.setParentId(id);
                        //模块id
                        dataInfoLog.setModuleId(ModuleTypeEnum.BUSINESS_OFFER.getId());
                        //操作人编码
                        dataInfoLog.setOperationCode(createNo);
                        //操作人名称
                        dataInfoLog.setOperationName(creator);
                        //操作类型
                        dataInfoLog.setOperationType(OperationTypeEnum.UPDATE_DATA.getId());
                        //操作时间
                        dataInfoLog.setOperationTime(new Date());
                        //操作内容
                        dataInfoLog.setOperationContent("产品信息:" + info);

                        dataInfoLogService.insert(dataInfoLog);
                    }

                    //获取明细id
                    newIds.add(detailReq.getId());
                    //设置修改时间
                    offerDetail.setModifyTime(new Date());
                    //明细修改
                    offerDetailService.update(offerDetail);
                    //配件修改
                    if(!CollectionUtils.isEmpty(detailReq.getPartsList())){
                        List<Integer> newPartsIds = new ArrayList<>();
                        for(AddOfferProductPartsReq parts : detailReq.getPartsList()){
                            if(null == parts.getId()){
                                //新增
                                //初始化配件对象
                                OfferProductPartsEntity partsEntity = new OfferProductPartsEntity();
                                //赋值
                                BeanUtils.copyProperties(parts, partsEntity);
                                //报价id
                                partsEntity.setParentId(id);
                                //产品明细id
                                partsEntity.setProductDetailId(detailReq.getId());
                                //创建时间
                                partsEntity.setCreateDate(new Date());
                                //产品类型(1:成品 2:配件 默认为配件)
                                partsEntity.setProductType(ProductTypeEnum.FITTING.getId());
                                //设置数据有效性(0:无效 1:有效)
                                partsEntity.setValid(DataIsValidEnum.VALID.getId());

                                offerProductPartsService.insert(partsEntity);
                                //获取配件id
                                newPartsIds.add(partsEntity.getId());
                            }else {
                                //修改
                                if(detailReq.getId().equals(parts.getProductDetailId())){
                                    //获取配件id
                                    newPartsIds.add(parts.getId());
                                    //初始化配件对象
                                    OfferProductPartsEntity partsEntity = new OfferProductPartsEntity();
                                    //赋值
                                    BeanUtils.copyProperties(parts, partsEntity);
                                    //修改时间
                                    partsEntity.setModifyTime(new Date());

                                    offerProductPartsService.update(partsEntity);
                                }
                            }

                        }
                        //处理被删除的配件
                        handleBeenDeletedParts(detailReq.getId(), newPartsIds);
                    }
                }

            }

            //处理被删除的明细
            handleBeenDeletedDetail(req, id, newIds, creator, createNo);

        }
    }

    /**
     * 处理被删除的配件
     * @param id 产品明细id
     * @param newIds 配件id
     */
    private void handleBeenDeletedParts(int id, List<Integer> newIds){
        //修改-找出被删除的明细

        OfferProductPartsEntity partsReq = new OfferProductPartsEntity();
        //设置产品明细id
        partsReq.setProductDetailId(id);
        //查询有效数据
        partsReq.setValid(DataIsValidEnum.VALID.getId());
        //调用接口查询结果
        List<OfferProductPartsEntity> partsList = offerProductPartsService.queryAll(partsReq);
        if(!CollectionUtils.isEmpty(partsList)){
            //获取id集合
            List<Integer> oldIds = partsList.stream().map(p -> p.getId()).collect(Collectors.toList());
            //找出被删除的id
            Collection collection = new ArrayList(oldIds);
            collection.removeAll(newIds);
            if(collection.size() > 0){
                //遍历删除被删除的明细
                Iterator<Integer> ids = collection.iterator();
                while (ids.hasNext()){
                    int partsId = ids.next();
                    OfferProductPartsEntity updateReq = new OfferProductPartsEntity();
                    //修改主键
                    updateReq.setId(partsId);
                    //修改时间
                    updateReq.setModifyTime(new Date());
                    //设为无效
                    updateReq.setValid(DataIsValidEnum.INVALID.getId());

                    offerProductPartsService.update(updateReq);

                }
            }
        }
    }

    /**
     * 处理被删除的付款明细
     * @param req 明细
     * @param id 主表id
     * @param newIds 修改后未被删除的细id集合
     */
    private void handleBeenDeletedDetail(AddOfferReq req, int id, List<Integer> newIds, String creator, String createNo){
        if(null != req.getId()){
            //修改-找出被删除的明细

            OfferDetailEntity detailReq = new OfferDetailEntity();
            //设置付款id
            detailReq.setParentId(id);
            //查询有效数据
            detailReq.setValid(DataIsValidEnum.VALID.getId());
            //调用接口查询结果
            List<OfferDetailEntity> detailList = offerDetailService.queryAll(detailReq);
            if(!CollectionUtils.isEmpty(detailList)){
                //获取id集合
                List<Integer> oldIds = detailList.stream().map(p -> p.getId()).collect(Collectors.toList());
                //找出被删除的id
                Collection collection = new ArrayList(oldIds);
                collection.removeAll(newIds);
                if(collection.size() > 0){
                    //遍历删除被删除的明细
                    Iterator<Integer> ids = collection.iterator();
                    while (ids.hasNext()){
                        int detailId = ids.next();
                        //添加日志
                        OfferDetailEntity detailEntity = offerDetailService.queryById(detailId);
                        //新增日志信息
                        DataInfoLogEntity dataInfoLog = new DataInfoLogEntity();
                        //模块主表id
                        dataInfoLog.setParentId(id);
                        //模块id
                        dataInfoLog.setModuleId(ModuleTypeEnum.BUSINESS_OFFER.getId());
                        //操作人编码
                        dataInfoLog.setOperationCode(createNo);
                        //操作人名称
                        dataInfoLog.setOperationName(creator);
                        //操作类型
                        dataInfoLog.setOperationType(OperationTypeEnum.DELETE_DATA.getId());
                        //操作时间
                        dataInfoLog.setOperationTime(new Date());
                        //操作内容
                        dataInfoLog.setOperationContent("产品信息:" + "产品编码:" + detailEntity.getProductCode() + ",规格编码:" + detailEntity.getSpecificationCode());

                        dataInfoLogService.insert(dataInfoLog);

                        OfferDetailEntity detail = new OfferDetailEntity();
                        detail.setId(detailId);
                        detail.setModifyTime(new Date());
                        detail.setValid(DataIsValidEnum.INVALID.getId());
                        //将删除的明细设为无效
                        offerDetailService.update(detail);

                        //获取对应的配件数据
                        OfferProductPartsEntity query = new OfferProductPartsEntity();
                        //报价id
                        query.setParentId(id);
                        //产品明细id
                        query.setProductDetailId(detailId);
                        //有效的数据
                        query.setValid(DataIsValidEnum.VALID.getId());
                        //调用接口查询
                        List<OfferProductPartsEntity> partsList = offerProductPartsService.queryAll(query);
                        if(!CollectionUtils.isEmpty(partsList)){
                            for(OfferProductPartsEntity partsEntity : partsList){
                                OfferProductPartsEntity updateReq = new OfferProductPartsEntity();
                                //修改主键
                                updateReq.setId(partsEntity.getId());
                                //修改时间
                                updateReq.setModifyTime(new Date());
                                //设为无效
                                updateReq.setValid(DataIsValidEnum.INVALID.getId());

                                offerProductPartsService.update(updateReq);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 新增报价主表信息
     * @param req 新增参数
     * @param creator 创建人
     * @param createNo 创建人编码
     * @return 报价主表id
     * @throws ParseException
     */
    private Integer insert(AddOfferReq req, String creator, String createNo) throws ParseException {
        //初始化对象
        OfferEntity offer = new OfferEntity();
        //赋值
        BeanUtils.copyProperties(req, offer);
        //报价日期
        offer.setTime(DateUtils.convertStringToDate(req.getTime(), DateUtils.DATE_PATTERN));
        //报价有效期限
        offer.setTermOfValidity(DateUtils.convertStringToDate(req.getTermOfValidity(), DateUtils.DATE_PATTERN));
        //交货期限
        offer.setDeliveryPeriod(DateUtils.convertStringToDate(req.getDeliveryPeriod(), DateUtils.DATE_PATTERN));
        //保存后进草稿箱
        offer.setStatus(OperationStatusEnum.DRAFT_BOX.getId());
        //设置数据有效性(0:无效 1:有效)
        offer.setValid(DataIsValidEnum.VALID.getId());

        if(null == req.getId()){
            //新增
            //设置创建时间
            offer.setCreateDate(new Date());
            //设置创建人
            offer.setOperation(creator);
            //设置创建人编码
            offer.setOperationNo(createNo);
            //调用接口新增调拨
            return offerService.insert(offer) == 1 ? offer.getId() : null;
        }else {
            //修改

            //如果明细、费用为空，则删除对应所有明细和费用
            if(CollectionUtils.isEmpty(req.getDetailList())){
                OfferDetailEntity detailReq = new OfferDetailEntity();
                //设置报价id
                detailReq.setParentId(req.getId());
                //数据有效
                detailReq.setValid(DataIsValidEnum.VALID.getId());
                List<OfferDetailEntity> detailList = offerDetailService.queryAll(detailReq);
                if(!CollectionUtils.isEmpty(detailList)){
                    for(OfferDetailEntity detail : detailList){
                        OfferDetailEntity updateReq = new OfferDetailEntity();
                        //主键id
                        updateReq.setId(detail.getId());
                        //修改时间
                        updateReq.setModifyTime(new Date());
                        //设为无效
                        updateReq.setValid(DataIsValidEnum.INVALID.getId());

                        offerDetailService.update(updateReq);
                    }
                }
            }

            if(CollectionUtils.isEmpty(req.getCostList())){
                OfferCostEntity costReq = new OfferCostEntity();
                //设置报价id
                costReq.setParentId(req.getId());
                //数据有效
                costReq.setValid(DataIsValidEnum.VALID.getId());
                List<OfferCostEntity> costList = offerCostService.queryAll(costReq);
                if(!CollectionUtils.isEmpty(costList)){
                    for(OfferCostEntity cost : costList){
                        OfferCostEntity updateReq = new OfferCostEntity();
                        //主键id
                        updateReq.setId(cost.getId());
                        //修改时间
                        updateReq.setModifyTime(new Date());
                        //设为无效
                        updateReq.setValid(DataIsValidEnum.INVALID.getId());

                        offerCostService.update(updateReq);
                    }
                }
            }
            //设置修改时间
            offer.setModifyTime(new Date());

            //添加修改日志
            //获取修改前对象数据
            OfferEntity oldOffer = offerService.queryById(req.getId());
            BeanChangeLogUtil logUtil = new BeanChangeLogUtil();
            String info = logUtil.contrastObj(oldOffer, offer);
            if(StringUtils.isNotEmpty(info)){
                //新增日志信息
                DataInfoLogEntity dataInfoLog = new DataInfoLogEntity();
                //模块主表id
                dataInfoLog.setParentId(req.getId());
                //模块id
                dataInfoLog.setModuleId(ModuleTypeEnum.BUSINESS_OFFER.getId());
                //操作人编码
                dataInfoLog.setOperationCode(createNo);
                //操作人名称
                dataInfoLog.setOperationName(creator);
                //操作类型
                dataInfoLog.setOperationType(OperationTypeEnum.UPDATE_DATA.getId());
                //操作时间
                dataInfoLog.setOperationTime(new Date());
                //操作内容
                dataInfoLog.setOperationContent("主信息:" + info);

                dataInfoLogService.insert(dataInfoLog);
            }
            return offerService.update(offer) == 1 ? offer.getId() : null;
        }

    }

    /**
     * 校验单号是否存在
     * @param billNo 单号
     * @return true:不重复 false:重复
     */
    private boolean checkRepeatBillNo(String billNo){
        OfferEntity req = new OfferEntity();
        req.setBillNo(billNo);
        req.setValid(DataIsValidEnum.VALID.getId());
        List<OfferEntity> offerList = offerService.queryAll(req);
        if(CollectionUtils.isEmpty(offerList)){
            return true;
        }
        return false;
    }


    /**
     * 报价详情
     * @param id 报价id
     * @return 报价详情
     */
    public OfferDetailVo detail(Integer id){
        //初始化回参对象
        OfferDetailVo vo = new OfferDetailVo();
        if(null == id){
            return vo;
        }
        //第一步：获取主表信息
        OfferEntity offer = offerService.queryById(id);
        if(null == offer || null == offer.getId()){
            return vo;
        }
        //赋值
        BeanUtils.copyProperties(offer, vo);
        //设置报价时间
        vo.setTime(DateUtils.format(offer.getTime(), DateUtils.DATE_PATTERN));
        //报价有效期限
        vo.setTermOfValidity(DateUtils.format(offer.getTermOfValidity(), DateUtils.DATE_PATTERN));
        //交货期限
        vo.setDeliveryPeriod(DateUtils.format(offer.getDeliveryPeriod(), DateUtils.DATE_PATTERN));

        //第二步：获取产品明细数据
        OfferDetailEntity offerDetailReq = new OfferDetailEntity();
        //报价id
        offerDetailReq.setParentId(id);
        //有效数据
        offerDetailReq.setValid(DataIsValidEnum.VALID.getId());
        //调用接口查询报价产品明细数据
        List<OfferDetailEntity> offerDetailList = offerDetailService.queryAll(offerDetailReq);
        if(!CollectionUtils.isEmpty(offerDetailList)){
            //初始化回参对象集合
            List<OfferProductDetailVo> detailList = new ArrayList<>();
            for(OfferDetailEntity detailEntity : offerDetailList){
                //初始化回参对象
                OfferProductDetailVo productDetailVo = new OfferProductDetailVo();
                //赋值
                BeanUtils.copyProperties(detailEntity, productDetailVo);
                //获取该产品被下游调用数量
                BigDecimal sum = getRemainingQuantity(offer.getBillNo(), detailEntity.getProductCode(), detailEntity.getSpecificationCode());
                if(sum.compareTo(BigDecimal.ZERO) == 1){
                    //结果大于零，表明该数据被下游调用，不能删除
                    productDetailVo.setIsDelete(1);
                }else {
                    //结果小于等于零，表明该数据未被下游调用，可删除
                    productDetailVo.setIsDelete(0);
                }
                //获取对应配件信息
                OfferProductPartsEntity partsReq = new OfferProductPartsEntity();
                //设置报价id
                partsReq.setParentId(id);
                //设置产品明细id
                partsReq.setProductDetailId(detailEntity.getId());
                //设置数据有效性
                partsReq.setValid(DataIsValidEnum.VALID.getId());
                //查询结果
                List<OfferProductPartsEntity> partsEntityList = offerProductPartsService.queryAll(partsReq);
                if(!CollectionUtils.isEmpty(partsEntityList)){
                    List<OfferProductPartsDetailVo> partsList = partsEntityList.stream().map(p ->{
                        OfferProductPartsDetailVo partsVo = new OfferProductPartsDetailVo();
                        //赋值
                        BeanUtils.copyProperties(p, partsVo);
                        return partsVo;
                    }).collect(Collectors.toList());

                    //添加相关配件集合
                    productDetailVo.setPartsList(partsList);
                }

                detailList.add(productDetailVo);
            }
            //添加产品明细数据
            vo.setDetailList(detailList);
        }

        //第三步：获取费用数据
        OfferCostEntity costReq = new OfferCostEntity();
        //设置报价id
        costReq.setParentId(id);
        //获取有效数据
        costReq.setValid(DataIsValidEnum.VALID.getId());
        //查询结果
        List<OfferCostEntity> costEntities = offerCostService.queryAll(costReq);
        if(!CollectionUtils.isEmpty(costEntities)){
            List<OfferCostDetailVo> costList = costEntities.stream().map(p ->{
                OfferCostDetailVo costVo = new OfferCostDetailVo();
                //赋值
                BeanUtils.copyProperties(p, costVo);
                return costVo;
            }).collect(Collectors.toList());

            //添加相关费用信息
            vo.setCostList(costList);
        }

        //第四步：获取对应附件信息
        getAnnexDetail(id, vo);

        //第五步：获取对应日志信息
        DataInfoLogEntity logReq = new DataInfoLogEntity();
        //主表id
        logReq.setParentId(id);
        //模块id
        logReq.setModuleId(ModuleTypeEnum.BUSINESS_OFFER.getId());
        //查询结果
        List<DataInfoLogEntity> dataInfoLog = dataInfoLogService.queryAll(logReq);
        if(!CollectionUtils.isEmpty(dataInfoLog)){
            List<DataInfoLogVo> logVos = new ArrayList<>();
            for(DataInfoLogEntity log : dataInfoLog){
                DataInfoLogVo logVo = new DataInfoLogVo();
                //赋值
                BeanUtils.copyProperties(log, logVo);
                //日期处理
                logVo.setOperationTime(DateUtils.format(log.getOperationTime(), DateUtils.DATE_TIME_PATTERN));
                //操作类型
                logVo.setOperationType(OperationTypeEnum.getDescById(log.getOperationType()));

                logVos.add(logVo);
            }

            vo.setLogList(logVos);
        }

        return vo;
    }

    /**
     * 获取附件详情
     * @param id 报价id
     * @param vo 回参实体
     */
    private void getAnnexDetail(Integer id, OfferDetailVo vo) {
        AnnexEntity annex = new AnnexEntity();
        //设置模块id
        annex.setModuleId(ModuleTypeEnum.BUSINESS_OFFER.getId());
        //设置父id
        annex.setParentId(id);
        //设置数据有效
        annex.setValid(DataIsValidEnum.VALID.getId());
        //调用接口查询附件信息
        List<AnnexEntity> annexList = annexService.queryAll(annex);
        if (CollectionUtils.isEmpty(annexList)) {
            return;
        }
        List<AnnexVo> annexVos = annexList.stream().map(p -> {
            AnnexVo annexVo = new AnnexVo();
            //赋值
            BeanUtils.copyProperties(p, annexVo);
            //上传时间转换
            annexVo.setUploadTime(DateUtils.format(p.getUploadTime(), DateUtils.DATE_TIME_PATTERN));
            //设置附件为旧附件,用以区分修改时附件状态
            annexVo.setNews(0);

            return annexVo;
        }).collect(Collectors.toList());

        vo.setAnnexList(annexVos);
    }

    /**
     * 删除
     * @param req
     */
    @Transactional(rollbackFor = Exception.class)
    public void delete(OperationReq req){
        if(null == req.getId() || null == req.getStatus()){
            return;
        }
        OfferEntity offerReq = new OfferEntity();
        offerReq.setId(req.getId());
        offerReq.setModifyTime(new Date());
        if(req.getStatus().equals(OperationStatusEnum.DRAFT_BOX.getId())){
            //草稿箱删除,数位改为垃圾箱
            offerReq.setStatus(OperationStatusEnum.TRASH_CAN.getId());
            offerService.update(offerReq);
            return;
        }else {
            //垃圾箱删除,将主数据设为无效
            offerReq.setValid(DataIsValidEnum.INVALID.getId());
            offerService.update(offerReq);
        }
        //获取对应明细数据
        OfferDetailEntity detailEntity = new OfferDetailEntity();
        detailEntity.setParentId(req.getId());
        detailEntity.setValid(DataIsValidEnum.VALID.getId());

        List<OfferDetailEntity> detailList = offerDetailService.queryAll(detailEntity);
        if(CollectionUtils.isEmpty(detailList)){
            return;
        }
        //将所有对应有效的明细数据设为无效
        for(OfferDetailEntity detail : detailList){
            OfferDetailEntity detailReq = new OfferDetailEntity();
            detailReq.setId(detail.getId());
            detailReq.setModifyTime(new Date());
            detailReq.setValid(DataIsValidEnum.INVALID.getId());

            offerDetailService.update(detailReq);
        }

        //获取费用数据
        OfferCostEntity costEntity = new OfferCostEntity();
        costEntity.setParentId(req.getId());
        costEntity.setValid(DataIsValidEnum.VALID.getId());

        List<OfferCostEntity> costList = offerCostService.queryAll(costEntity);
        if(CollectionUtils.isEmpty(costList)){
            return;
        }
        //将所有对应有效的费用数据设为无效
        for(OfferCostEntity cost : costList){
            OfferCostEntity costReq = new OfferCostEntity();
            costReq.setId(cost.getId());
            costReq.setModifyTime(new Date());
            costReq.setValid(DataIsValidEnum.INVALID.getId());

            offerCostService.update(costReq);
        }

        //获取对应所有附件
        AnnexEntity annex = new AnnexEntity();
        annex.setModuleId(ModuleTypeEnum.BUSINESS_OFFER.getId());
        annex.setParentId(req.getId());
        annex.setValid(DataIsValidEnum.VALID.getId());
        List<AnnexEntity> annexList = annexService.queryAll(annex);
        if(CollectionUtils.isEmpty(annexList)){
            return;
        }
        //删除所有对应的有效的附件
        for(AnnexEntity annexData : annexList){
            AnnexEntity annexReq = new AnnexEntity();
            annexReq.setId(annexData.getId());
            annexReq.setUpdateTime(new Date());
            annexReq.setValid(DataIsValidEnum.INVALID.getId());

            annexService.update(annexReq);
        }
    }

    /**
     * 收款首页-箱体操作
     * @param req
     */
    public R operation(OperationReq req){
        if(null == req.getId() || null == req.getOperation() || StringUtils.isBlank(req.getBillNo())){
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }
        OfferEntity offerEntity = new OfferEntity();
        //设置修改主键
        offerEntity.setId(req.getId());
        //修改时间
        offerEntity.setModifyTime(new Date());

        switch (req.getOperation()){
            case 1:
                //提交审批后,状态为待批箱
                offerEntity.setStatus(OperationStatusEnum.PENDING_BOX.getId());
                break;
            case 2:
                //审批通过,状态设为已批箱
                offerEntity.setStatus(OperationStatusEnum.APPROVED_BOX.getId());
                break;
            case 3:
                //审批退回
                //校验是否可以回退数据 true:是 false:否
                boolean flag = checkDataIsRollBack(req.getId(), req.getBillNo());
                if(flag){
                    //状态设为草稿箱
                    offerEntity.setStatus(OperationStatusEnum.DRAFT_BOX.getId());
                }else {
                    //审批退回失败,存在已被调用的产品
                    return R.buildError(ResultStatusEnum.APPROVAL_RETURNED_FAILED);
                }
                break;
            case 4:
                //将状态设为完成
                offerEntity.setStatus(OperationStatusEnum.COMPLETION_BOX.getId());
                break;
            case 5:
                //点击还原，将状态改为草稿箱
                offerEntity.setStatus(OperationStatusEnum.DRAFT_BOX.getId());
                break;
        }
        //调用接口修改
        offerService.update(offerEntity);
        return R.buildError(ResultStatusEnum.SUCCESS);
    }

    /**
     * 批量操作
     * @param req 操作数据实体
     * @param msn 是否管理层
     * @return 批量操作结果
     */
    public R batchOperation(BatchOperationReq req, String msn){
        if(!"是".equals(msn)){
            return R.buildError(ResultStatusEnum.INSUFFICIENT_PERMISSION_ERROR);
        }
        if(CollectionUtils.isEmpty(req.getOperationReqs())){
            return R.buildError(ResultStatusEnum.SUCCESS);
        }
        switch (req.getType()){
            case 1:
                for(OperationReq operationReq : req.getOperationReqs()){
                    if(OperationStatusEnum.DRAFT_BOX.getId() == operationReq.getStatus()){
                        OfferEntity offerEntity = new OfferEntity();
                        //设置修改主键
                        offerEntity.setId(operationReq.getId());
                        //修改时间
                        offerEntity.setModifyTime(new Date());
                        //提交审批后,状态为待批箱
                        offerEntity.setStatus(OperationStatusEnum.PENDING_BOX.getId());
                        //调用接口修改
                        offerService.update(offerEntity);
                    }
                }
                break;
            case 2:
                for(OperationReq operationReq : req.getOperationReqs()){
                    if(OperationStatusEnum.PENDING_BOX.getId() == operationReq.getStatus()){
                        OfferEntity offerEntity = new OfferEntity();
                        //设置修改主键
                        offerEntity.setId(operationReq.getId());
                        //修改时间
                        offerEntity.setModifyTime(new Date());
                        //审批通过,状态设为已批箱
                        offerEntity.setStatus(OperationStatusEnum.APPROVED_BOX.getId());
                        //调用接口修改
                        offerService.update(offerEntity);
                    }
                }
                break;
            default:
                break;
        }
        return R.buildError(ResultStatusEnum.SUCCESS);
    }


    /**
     * 校验是否可以回退数据 true:是 false:否
     * @param id 报价id
     * @param billNo 报价单号
     * @return 是否可以回退数据
     */
    private Boolean checkDataIsRollBack(Integer id, String billNo){
        OfferDetailEntity offerDetailReq = new OfferDetailEntity();
        //设置父id
        offerDetailReq.setParentId(id);
        //设置数据有效
        offerDetailReq.setValid(DataIsValidEnum.VALID.getId());
        //获取报价产品信息
        List<OfferDetailEntity> offerDetailList = offerDetailService.queryAll(offerDetailReq);
        if(CollectionUtils.isEmpty(offerDetailList)){
            return true;
        }
        BigDecimal sum = new BigDecimal("0");
        for(OfferDetailEntity detail : offerDetailList){
            //获取该产品在外销产品中的数量
            BigDecimal quantity = getRemainingQuantity(billNo, detail.getProductCode(), detail.getSpecificationCode());
            //数量累加
            sum = sum.add(quantity);
        }
        if(sum.compareTo(BigDecimal.ZERO) == 1){
            //结果大于零,不能回退数据
            return false;
        }
        return true;
    }


    /**
     * 根据产品规格编码获取对应配件信息
     * @param specNo 产品规格编码
     * @param productCode 产品编码
     * @return 对应配件信息
     */
    public List<ProductPartsInfoVo> getProductPartsInfoBySpecNo(String specNo, String productCode){
        //初始化回参
        List<ProductPartsInfoVo> infoVos = new ArrayList<>();
        if(StringUtils.isBlank(specNo)){
            return infoVos;
        }
        //调用接口获取配件信息
        List<ProductPartsInfoRsp> partsList = stockService.getProductPartsInfoBySpecNo(specNo, productCode);
        if(CollectionUtils.isEmpty(partsList)){
            return infoVos;
        }
        for(ProductPartsInfoRsp parts : partsList){
            ProductPartsInfoVo vo = new ProductPartsInfoVo();
            //赋值
            BeanUtils.copyProperties(parts, vo);
            //成品比例
            BigDecimal proportionFinishedProducts = new BigDecimal("0");
            if(StringUtils.isNotBlank(parts.getProportionFinishedProducts())){
                proportionFinishedProducts = new BigDecimal(parts.getProportionFinishedProducts());
            }
            vo.setProportionFinishedProducts(proportionFinishedProducts);

            //配件比例
            BigDecimal partsFinishedProducts = new BigDecimal("0");
            if(StringUtils.isNotBlank(parts.getPartsFinishedProducts())){
                partsFinishedProducts = new BigDecimal(parts.getPartsFinishedProducts());
            }
            vo.setPartsFinishedProducts(partsFinishedProducts);

            //毛重
            BigDecimal grossWeight = new BigDecimal("0");
            if(StringUtils.isNotBlank(parts.getGrossWeight())){
                grossWeight = new BigDecimal(parts.getGrossWeight());
            }
            vo.setGrossWeight(grossWeight);

            //净重
            BigDecimal netWeight = new BigDecimal("0");
            if(StringUtils.isNotBlank(parts.getNetWeight())){
                netWeight = new BigDecimal(parts.getNetWeight());
            }
            vo.setNetWeight(netWeight);

            //体积
            BigDecimal bulk = new BigDecimal("0");
            if(StringUtils.isNotBlank(parts.getBulk())){
                bulk = new BigDecimal(parts.getBulk());
            }
            vo.setBulk(bulk);

            infoVos.add(vo);
        }

        return infoVos;
    }

    /**
     * 根据产品编码获取对应附件信息
     * @param productCode 产品编码
     * @return 根据产品编码获取对应附件信息
     */
    public List<AnnexVo> getAnnexByProductCode(String productCode) {
        //初始化回参集合
        List<AnnexVo> voList = new ArrayList<>();
        if (StringUtils.isEmpty(productCode)) {
            return voList;
        }
        //获取附件信息
        List<ProductAnnexInfoRsp> productAnnex = stockService.getProductAnnexInfoByProductCode(productCode);
        if (CollectionUtils.isEmpty(productAnnex)) {
            return voList;
        }
        for (ProductAnnexInfoRsp annexInfo : productAnnex) {
            String path = annexInfo.getPath();
            if (StringUtils.isEmpty(path)) {
                continue;
            }
            AnnexVo annexVo = new AnnexVo();
            //获取文件真实路径
            String filePath = path.substring(path.indexOf("pathname=") + 9, path.indexOf("productwj") + 9);
            //获取真实文件名
            String fileName = path.substring(path.indexOf("&filename=") + 10, path.indexOf("&originalFileName="));
            annexVo.setId(annexInfo.getId());
            annexVo.setFilePath(filePath + "/" + fileName);
            annexVo.setUploadTime(DateUtils.format(new Date()));
            //获取上传时附件名称
            String originalFileName = path.substring(path.indexOf("&originalFileName=") + 18);
            annexVo.setFileName(originalFileName);

            voList.add(annexVo);
        }
        return voList;
    }

    /**
     * 获取外销产品表中存在指定报价单中的产品数量
     * @param billNo 报价单号
     * @param productCode 产品编码
     * @param specificationCode 规格编码
     * @return 外销产品表中存在指定报价单中的产品数量
     */
    private BigDecimal getRemainingQuantity(String billNo, String productCode, String specificationCode){
        //初始化查询参数
        RemainingQuantityReq req = new RemainingQuantityReq();
        //报价单号
        req.setBillNo(billNo);
        //产品编码
        req.setProductCode(productCode);
        //规格编码
        req.setSpecificationCode(specificationCode);
        //调用接口查询
        List<ExportContractProductEntity> quantityList = exportContractProductService.getOfferRemainingQuantity(req);
        //总数量
        BigDecimal sum = new BigDecimal("0");
        for(ExportContractProductEntity quantity : quantityList){
            if(StringUtil.isNotEmpty(quantity.getProductNum())){
                sum = sum.add(quantity.getProductNum());
            }
        }
        return sum;
    }

    /**
     * 统计
     * @param req 查询条件
     * @return 统计
     */
    public PageInfo<OfferProductStatisticsVo> getOfferProductStatistics(OfferProductStatisticsReq req){
        //初始化查询条件
        OfferProductStatisticsInfoReq infoReq = new OfferProductStatisticsInfoReq();
        //赋值
        BeanUtils.copyProperties(req, infoReq);
        //调用接口查询
        List<OfferProductStatisticsRsp> statisticsList = offerDetailService.getOfferProductStatistics(infoReq);
        //初始化回参对象集合
        List<OfferProductStatisticsVo> voList = new ArrayList<>();
        PageInfo pageInfo = new PageInfo(statisticsList);
        if(CollectionUtils.isEmpty(statisticsList)){
            pageInfo.setList(voList);
            return pageInfo;
        }
        //报价统计数据整理
        voList = getOfferProductStatisticsDataInfo(statisticsList);

        pageInfo.setList(voList);
        return pageInfo;
    }

    /**
     * 统计 导出Excel
     * @param req 查询条件
     * @return 统计 导出Excel
     */
    public JSONObject getOfferProductStatisticsInfo(OfferProductStatisticsReq req){
        //初始化查询条件
        OfferProductStatisticsInfoReq infoReq = new OfferProductStatisticsInfoReq();
        //赋值
        BeanUtils.copyProperties(req, infoReq);
        //调用接口查询
        List<OfferProductStatisticsRsp> statisticsList = offerDetailService.getOfferProductStatistics(infoReq);
        JSONObject obj = new JSONObject();
        //获取excel的title信息
        JSONArray titleList = getTitleInfoOfOfferStatistics();
        JSONArray data = new JSONArray();
        data.add(titleList);
        if(CollectionUtils.isEmpty(statisticsList)){
            obj.put("data", data);
            return obj;
        }
        List<OfferProductStatisticsVo> voList = getOfferProductStatisticsDataInfo(statisticsList);

        //封装数据
        getOfferStatisticsInfo(data, voList);

        obj.put("data", data);
        return obj;
    }

    /**
     * 封装数据
     * @param data 封装后数据
     * @param voList 原始数据
     */
    private void getOfferStatisticsInfo(JSONArray data, List<OfferProductStatisticsVo> voList){
        BigDecimal amountUSD = new BigDecimal("0");
        BigDecimal amountRMB = new BigDecimal("0");
        BigDecimal productNum = new BigDecimal("0");
        for(OfferProductStatisticsVo vo : voList){
            JSONArray infoList = new JSONArray();
            infoList.add(getNotNullOfStringInfo(vo.getBillNo()));
            infoList.add(vo.getTime() == null ? "" : vo.getTime());
            infoList.add(getNotNullOfStringInfo(vo.getCustomerName()));
            infoList.add(getNotNullOfStringInfo(vo.getTermOfValidity()));
            infoList.add(getNotNullOfStringInfo(vo.getDeliveryPeriod()));
            infoList.add(getNotNullOfStringInfo(vo.getPriceTermsName()));
            infoList.add(getNotNullOfStringInfo(vo.getSalesman()));
            infoList.add(getNotNullOfStringInfo(vo.getOperation()));
            infoList.add(getNotNullOfStringInfo(vo.getCurrency()));
            infoList.add(getNotNullOfStringInfo(vo.getProductCode()));
            infoList.add(getNotNullOfStringInfo(vo.getSpecificationCode()));
            infoList.add(getNotNullOfStringInfo(vo.getProductCname()));
            infoList.add(getNotNullOfStringInfo(vo.getProductEname()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getUnitPrice()));
            if(StringUtil.isNotEmpty(vo.getProductNum())){
                productNum = productNum.add(vo.getProductNum());
            }
            infoList.add(getNotNullOfBigDecimalInfo(vo.getProductNum()));

            if(StringUtil.isNotEmpty(vo.getMoneySubtotalUSD())){
                amountUSD = amountUSD.add(vo.getMoneySubtotalUSD());
            }
            infoList.add(getNotNullOfBigDecimalInfo(vo.getMoneySubtotalUSD()));

            if(StringUtil.isNotEmpty(vo.getMoneySubtotalRMB())){
                amountRMB = amountRMB.add(vo.getMoneySubtotalRMB());
            }
            infoList.add(getNotNullOfBigDecimalInfo(vo.getMoneySubtotalRMB()));

            infoList.add(getNotNullOfStringInfo(vo.getIsDeal()));
            infoList.add(getNotNullOfStringInfo(vo.getSigningCompanyName()));
            infoList.add(getNotNullOfStringInfo(vo.getMemo()));

            data.add(infoList);
        }
        JSONArray titleList = new JSONArray();
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add(productNum);
        titleList.add(amountUSD);
        titleList.add(amountRMB);
        titleList.add("");
        titleList.add("");
        titleList.add("");

        data.add(titleList);
    }

    /**
     * 获取String类型不为空数据
     * @param value 目标数据
     * @return 不为空数据
     */
    private String getNotNullOfStringInfo(String value){
        if(StringUtils.isEmpty(value)){
            return "";
        }else {
            return value;
        }
    }

    /**
     * 获取BigDecimal类型不为空的数据
     * @param value 目标数据
     * @return 不为空数据
     */
    private BigDecimal getNotNullOfBigDecimalInfo(BigDecimal value){
        if(StringUtil.isNotEmpty(value)){
            return value;
        }else {
            return new BigDecimal("0");
        }
    }

    /**
     * 获取excel的title信息
     * @return excel的title信息
     */
    private JSONArray getTitleInfoOfOfferStatistics(){
        JSONArray titleList = new JSONArray();
        titleList.add("报价单号");
        titleList.add("报价日期");
        titleList.add("客户名称");
        titleList.add("报价有效期限");
        titleList.add("交货期限");
        titleList.add("价格术语");
        titleList.add("业务员");
        titleList.add("操作员");
        titleList.add("币种");
        titleList.add("产品编码");
        titleList.add("规格编码");
        titleList.add("中文名称");
        titleList.add("英文名称");
        titleList.add("单价");
        titleList.add("数量");
        titleList.add("USD金额小计");
        titleList.add("RMB金额小计");
        titleList.add("是否成交");
        titleList.add("签约公司");
        titleList.add("备注");

        return titleList;
    }

    /**
     * 报价统计数据整理
     * @param statisticsList  报价统计数据
     * @return
     */
    private List<OfferProductStatisticsVo> getOfferProductStatisticsDataInfo(List<OfferProductStatisticsRsp> statisticsList){
        //初始化回参对象集合
        List<OfferProductStatisticsVo> voList = new ArrayList<>();
        //查询是否成交
        for(OfferProductStatisticsRsp statisticsRsp : statisticsList){
            //初始化回参对象
            OfferProductStatisticsVo vo = new OfferProductStatisticsVo();
            //赋值
            BeanUtils.copyProperties(statisticsRsp, vo);
            //报价日期
            vo.setTime(DateUtils.format(statisticsRsp.getTime()));
            //报价有效期限
            vo.setTermOfValidity(DateUtils.format(statisticsRsp.getTermOfValidity()));
            //交货期限
            vo.setDeliveryPeriod(DateUtils.format(statisticsRsp.getDeliveryPeriod()));
            //单价
            BigDecimal unitPrice = new BigDecimal("0");
            if(StringUtil.isNotEmpty(statisticsRsp.getUnitPrice())){
                unitPrice = statisticsRsp.getUnitPrice();
            }
            //人民币汇率
            BigDecimal rmbRate = new BigDecimal("0");
            if(StringUtil.isNotEmpty(statisticsRsp.getRmbRate())){
                rmbRate = statisticsRsp.getRmbRate();
            }
            //美金汇率
            BigDecimal usdRate = new BigDecimal("0");
            if(StringUtil.isNotEmpty(statisticsRsp.getUsdRate())){
                usdRate = statisticsRsp.getUsdRate();
            }
            //数量
            BigDecimal productNum = new BigDecimal("0");
            if(StringUtil.isNotEmpty(statisticsRsp.getProductNum())){
                productNum = statisticsRsp.getProductNum();
            }
            //USD金额小计
            vo.setMoneySubtotalUSD(unitPrice.multiply(usdRate).multiply(productNum));
            if("usd-001".equals(statisticsRsp.getCurrency()) || "rmb-001".equals(statisticsRsp.getCurrency())){
                //RMB金额小计
                vo.setMoneySubtotalRMB(unitPrice.multiply(rmbRate).multiply(productNum));
            }else {
                //RMB金额小计
                vo.setMoneySubtotalRMB(unitPrice.multiply(usdRate).multiply(rmbRate).multiply(productNum));
            }
            //初始化查询条件
            ExportContractProductEntity exportReq = new ExportContractProductEntity();
            //有效
            exportReq.setValid(DataIsValidEnum.VALID.getId());
            //产品编码
            exportReq.setProductCode(statisticsRsp.getProductCode());
            //规格编码
            exportReq.setSpecificationCode(statisticsRsp.getSpecificationCode());
            //报价单号
            exportReq.setOfferBillNo(statisticsRsp.getBillNo());
            //调用接口查询结果
            List<ExportContractProductEntity> contractList = exportContractProductService.queryAll(exportReq);
            if(CollectionUtils.isEmpty(contractList) || contractList.size() <= 0){
                vo.setIsDeal("否");
            }else {
                vo.setIsDeal("是");
            }

            voList.add(vo);
        }
        return voList;
    }


    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    public OfferEntity queryById(Integer id){
        return offerService.queryById(id);
    }
    /**
     * 根据参数返回拼接之后的logo的url
     * @param id
     * @return
     */
    public CompanyLogo getImgLogoUrl(Integer id){
        return offerService.getImgLogoUrl(id);
    }

    /**
     * 获取本月报价总额USD
     * @param name 操作员
     * @param code 操作员编码
     * @return 本月报价总额USD
     */
    public BigDecimal getOfferTotalContractAmount(String name, String code){
        //初始化查询对象
        StatisticsInfoReq infoReq = new StatisticsInfoReq();
        infoReq.setOperator(name);
        infoReq.setOperationCode(code);
        infoReq.setCreateDateStart(DateUtils.format(DateUtils.getStartTimeOfTheMonth(), DateUtils.DATE_PATTERN));
        infoReq.setCreateDateEnd(DateUtils.format(DateUtils.getEndTimeOfTheMonth(), DateUtils.DATE_PATTERN));
        //查询结果
        List<OfferEntity> offerList = offerService.getOfferInfo(infoReq);
        if(CollectionUtils.isEmpty(offerList)){
            return new BigDecimal("0.00");
        }
        //本月报价合同总额USD
        BigDecimal num = new BigDecimal("0");
        for(OfferEntity offer : offerList){
            //美金汇率
            BigDecimal usdRate = new BigDecimal("0");
            if(StringUtil.isNotEmpty(offer.getUsdRate())){
                usdRate = offer.getUsdRate();
            }
            //合同总额
            BigDecimal totalContractAmount = new BigDecimal("0");
            if(StringUtil.isNotEmpty(offer.getTotalQuotation())){
                totalContractAmount = offer.getTotalQuotation();
            }
            BigDecimal usdAmount = usdRate.multiply(totalContractAmount);

            num = num.add(usdAmount);
        }
        return num;
    }

    /**
     * 生成最新报价单号
     * @return 新报价单号
     */
    public String getOfferBillNo(){
        //初始化查询对象
        OfferListReq req = new OfferListReq();
        //当前年月日
        String currentDate = DateUtils.format(new Date());
        //创建时间(起止)
        String createDateStart = currentDate + " 00:00:00";
        req.setCreateDateStart(createDateStart);
        //创建时间(截至)
        String createDateEnd = currentDate + " 23:59:59";
        req.setCreateDateEnd(createDateEnd);
        List<OfferEntity> offer = offerService.getOfferBillNoByQuery(req);
        if(CollectionUtils.isEmpty(offer)){
            //当天未创建单据，单号从001开始
            return "BJ" + currentDate.replace("-", "") + "001";
        }
        //当天已创建单号,获取最后创建的单号
        String billNo = offer.get(0).getBillNo();
        //截取最后三位序列号
        String serialNumber = billNo.substring(billNo.length()-3);
        //数据转换
        BigDecimal formatBigDecimal = new BigDecimal(serialNumber);
        //生成新的序列号(序列号自增一位)
        String newSerialNumber = formatBigDecimal.add(new BigDecimal("1")).toString();
        if(1 == newSerialNumber.length()){
            newSerialNumber = "00" + newSerialNumber;
        }else if(2 == newSerialNumber.length()){
            newSerialNumber = "0" + newSerialNumber;
        }
        //生成最新报价单号
        return "BJ" + currentDate.replace("-", "") + newSerialNumber;
    }

    /**
     * 出口业务-报价-修改标记颜色
     *
     * @param req 入参实体
     */
    public void updateMarkColor(OperationReq req) {
        if (null == req || null == req.getId()) {
            return;
        }
        OfferEntity offerReq = new OfferEntity();
        //设置修改主键
        offerReq.setId(req.getId());
        //设修改时间
        offerReq.setModifyTime(new Date());
        //设置标记颜色
        offerReq.setMarkColor(req.getColor());
        //更新标记颜色
        offerService.updateMarkColor(offerReq);
    }

    /**
     * 获取备选供应商
     *
     * @param supplierCode 供应商编码
     * @return 备选供应商
     */
    public List<AlternativeSupplierVo> getAlternativeSupplierList(String supplierCode) {
        //初始化回参对象集合
        List<AlternativeSupplierVo> voList = new ArrayList<>();
        if (StringUtils.isEmpty(supplierCode)) {
            return voList;
        }
        //查询结果:获取备选供应商
        List<AlternativeSupplierRsp> alternativeSupplierList = offerService.getAlternativeSupplierList(supplierCode);
        if (CollectionUtils.isEmpty(alternativeSupplierList)) {
            return voList;
        }
        for (AlternativeSupplierRsp alternative : alternativeSupplierList) {
            //初始化回参对象
            AlternativeSupplierVo vo = new AlternativeSupplierVo();
            //赋值
            BeanUtils.copyProperties(alternative, vo);
            //含税出厂价
            BigDecimal taxIncludedPrice = new BigDecimal("0");
            if (StringUtils.isNotEmpty(alternative.getTaxIncludedPrice())) {
                taxIncludedPrice = new BigDecimal(alternative.getTaxIncludedPrice());
            }
            vo.setTaxIncludedPrice(taxIncludedPrice);

            //未税出厂价
            BigDecimal untaxedPrice = new BigDecimal("0");
            if (StringUtils.isNotEmpty(alternative.getUntaxedPrice())) {
                untaxedPrice = new BigDecimal(alternative.getUntaxedPrice());
            }
            vo.setUntaxedPrice(untaxedPrice);

            //含税FOB价
            BigDecimal taxIncludedFob = new BigDecimal("0");
            if (StringUtils.isNotEmpty(alternative.getTaxIncludedFob())) {
                taxIncludedFob = new BigDecimal(alternative.getTaxIncludedFob());
            }
            vo.setTaxIncludedFob(taxIncludedFob);

            //未税FOB价
            BigDecimal untaxedFob = new BigDecimal("0");
            if (StringUtils.isNotEmpty(alternative.getUntaxedFob())) {
                untaxedFob = new BigDecimal(alternative.getUntaxedFob());
            }
            vo.setUntaxedFob(untaxedFob);

            voList.add(vo);
        }
        return voList;
    }
}
